package com.kaizzi.data.ppt.template;

import com.fasterxml.jackson.databind.JsonNode;
import com.kaizzi.data.common.been.NameDouble;
import com.kaizzi.data.common.been.SeriesData;
import com.kaizzi.data.jdl.service.LogService;
import com.kaizzi.data.ppt.TemplateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xslf.usermodel.XSLFChart;
import org.apache.poi.xslf.usermodel.XSLFShape;
import org.apache.poi.xslf.usermodel.XSLFTextParagraph;
import org.apache.poi.xslf.usermodel.XSLFTextRun;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openxmlformats.schemas.drawingml.x2006.chart.*;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author Kzen
 * @Description description
 * @date 2020/9/27
 */
@Slf4j
@Component
public class Template18 {

    @Resource
    private TemplateUtil templateUtil;
    @Resource
    private LogService logService;

    public void text(List<XSLFTextParagraph> textParagraphs,JsonNode data) {
        if(textParagraphs==null||textParagraphs.size()==0){
            return;
        }
        for (XSLFTextParagraph textParagraph : textParagraphs) {
            if(textParagraph==null){
                continue;
            }
            List<XSLFTextRun> textRuns = textParagraph.getTextRuns();
            if(textRuns==null){
                continue;
            }
            for (XSLFTextRun textRun : textRuns) {
                if (textRun == null || textRun.getXmlObject()  == null){
                    return;
                }
                try {
                    if (textRun.getRawText().equals("18KEY-1")){
                        String title = data.get("title").asText();
                        templateUtil.text(textParagraph,title,false);
                        break;
                    }
                }catch (Exception e){
                    logService.setDataLogStatus("ppt-error");
                    log.error("page:{},text error :{}",10,e);
                }
            }
        }
    }

    public void barChart(CTPlotArea plot, JsonNode data, XSSFWorkbook workbook, XSSFSheet sheet, XSLFChart chart) {
        List<SeriesData> barData = getBarData(data);
        templateUtil.barChart(plot,barData,workbook,sheet,chart);
    }

    /**
     * 获取数据
     * @param jsonNode
     * @return
     */
    private static List<SeriesData> getBarData(JsonNode jsonNode){

        JsonNode tempData = jsonNode.get("data");
        List<SeriesData> seriesDatas = new ArrayList<>();
        List<NameDouble> nameDoubles1 = new ArrayList<>();
        List<NameDouble> nameDoubles2 = new ArrayList<>();
        List<NameDouble> nameDoubles3 = new ArrayList<>();

        for (JsonNode dateJson:tempData) {
            String date = dateJson.get("date").asText();
            NameDouble tempNameDouble1 = new NameDouble(date,dateJson.get("registUser").asDouble());
            NameDouble tempNameDouble2 = new NameDouble(date,dateJson.get("oldUser").asDouble());
            NameDouble tempNameDouble3 = new NameDouble(date,dateJson.get("activationUser").asDouble());
            nameDoubles1.add(tempNameDouble1);
            nameDoubles2.add(tempNameDouble2);
            nameDoubles3.add(tempNameDouble3);
        }

        SeriesData tempSerData1 = new SeriesData("每周激活的每周注册的新用户",nameDoubles1,"");
        SeriesData tempSerData2 = new SeriesData("每周找回老用户",nameDoubles2,"");
        SeriesData tempSerData3 = new SeriesData("每周激活用户",nameDoubles3,"");
        seriesDatas.add(tempSerData1);
        seriesDatas.add(tempSerData2);
        seriesDatas.add(tempSerData3);
        return seriesDatas;
    }

    public void lineChart(CTPlotArea plot, JsonNode data, XSSFWorkbook workbook, XSSFSheet sheet, XSLFChart chart) {
        List<SeriesData> lineData = getLineData(data);
        lineChart1(plot,lineData,workbook,sheet,chart);
    }

    private static List<SeriesData> getLineData(JsonNode jsonNode){

        JsonNode tempData = jsonNode.get("data");
        List<SeriesData> seriesDatas = new ArrayList<>();
        List<NameDouble> nameDoubles1 = new ArrayList<>();
        for (JsonNode dateJson:tempData) {
            String date = dateJson.get("date").asText();
            NameDouble tempNameDouble1 = new NameDouble(date,dateJson.get("activationRate").asDouble()/100);
            nameDoubles1.add(tempNameDouble1);
        }
        SeriesData tempSerData1 = new SeriesData("周维度用户总激活率",nameDoubles1,"");
        seriesDatas.add(tempSerData1);
        return seriesDatas;
    }

    /**
     * 18页这线图单独处理，结果暂时不需要转换
     * @param plot
     * @param seriesDatas
     */
    private void lineChart1(CTPlotArea plot ,List<SeriesData> seriesDatas, XSSFWorkbook workbook, XSSFSheet sheet, XSLFChart chart) {

        System.out.println("折线图");
        List<CTLineChart> lineChartList = plot.getLineChartList();
        for (CTLineChart lineChart:lineChartList){
            List<CTLineSer> serList = lineChart.getSerList();

            try {
                updateChartExcelV3(seriesDatas, workbook, sheet,3);
                workbook.write(chart.getPackagePart().getOutputStream());
            }catch (Exception e){
                logService.setDataLogStatus("ppt-error");
                log.error("写入excel 异常,异常原因:{}",e);
            }


            int i =0;
            for (CTLineSer ser:serList){
                try {
                    updateChartCatAndNum(seriesDatas.get(i),ser.getTx(),ser.getCat(),ser.getVal());
                    i++;
                }catch (Exception e){
                    logService.setDataLogStatus("ppt-error");
                    log.error("折线图异常");
                }
            }
        }
    }


    private void updateChartCatAndNum(SeriesData data, CTSerTx serTitle, CTAxDataSource catDataSource, CTNumDataSource numDataSource) {

        // 更新系列标题
        if (serTitle != null && serTitle.getStrRef() != null){
            serTitle.getStrRef().setF(serTitle.getStrRef().getF()); //
            serTitle.getStrRef().getStrCache().getPtArray(0).setV(data.name);
        }

        // TODO cat 也可能是 numRef
        long ptNumCnt = numDataSource.getNumRef().getNumCache().getPtCount().getVal();

        long ptCatCnt =0;
        if (catDataSource.getStrRef() ==null){
            ptCatCnt = catDataSource.getNumRef().getNumCache().getPtCount().getVal();
        }else {
            ptCatCnt = catDataSource.getStrRef().getStrCache().getPtCount().getVal();
        }

        int dataSize = data.value.size();
        System.out.println();
        for (int i = 0; i < dataSize; i++) {
            NameDouble cellValu = data.value.get(i);
            if (catDataSource.getStrRef() != null){
                CTStrVal cat = ptCatCnt > i ? catDataSource.getStrRef().getStrCache().getPtArray(i)
                        : catDataSource.getStrRef().getStrCache().addNewPt();
                cat.setIdx(i);
                cat.setV(cellValu.name);
            }else {
                CTNumVal cat = ptCatCnt > i ? catDataSource.getNumRef().getNumCache().getPtArray(i)
                        : catDataSource.getNumRef().getNumCache().addNewPt();
                cat.setIdx(i);
                cat.setV(cellValu.name);
            }

            CTNumVal val = ptNumCnt > i ? numDataSource.getNumRef().getNumCache().getPtArray(i)
                    : numDataSource.getNumRef().getNumCache().addNewPt();
            val.setIdx(i);
            val.setV(cellValu.value +"");
        }

        // 更新对应 excel 的range
        catDataSource.getStrRef().setF(
                replaceRowEnd(catDataSource.getStrRef().getF(),
                        ptCatCnt,
                        dataSize));
        numDataSource.getNumRef().setF(
                replaceRowEnd(numDataSource.getNumRef().getF(),
                        ptNumCnt,
                        dataSize));

        // 删除多的
        if (ptNumCnt > dataSize) {
            for (int idx = dataSize; idx < ptNumCnt; idx++) {
                catDataSource.getStrRef().getStrCache().removePt(dataSize);
                numDataSource.getNumRef().getNumCache().removePt(dataSize);
            }
        }
        // 更新个数
        catDataSource.getStrRef().getStrCache().getPtCount().setVal(dataSize);
        numDataSource.getNumRef().getNumCache().getPtCount().setVal(dataSize);
    }

    /**
     * 更新图表的关联 excel， 值是纵向的
     *
     * @param workbook
     * @param sheet
     */
    protected void updateChartExcelV3(List<SeriesData> seriesDatas, XSSFWorkbook workbook, XSSFSheet sheet,int colNo) {
//        System.out.println(JsonUtil.serialize(seriesDatas));
//        XSSFRow title = sheet.getRow(0);
        for (int i = 0; i < seriesDatas.size(); i++) {
            //折线图再第几列下标-1
            i = colNo;
            SeriesData data = seriesDatas.get(0);
//            if (data.name != null && !data.name.isEmpty()) {
//                // 系列名称，不能修改，修改后无法打开 excel
//                //                title.getCell(i + 1).setCellValue(data.name);
//            }
            int size = data.value.size();
            for (int j = 0; j < size; j++) {
                XSSFRow row = sheet.getRow(j + 1);
                if (row == null) {
                    row = sheet.createRow(j + 1);
                }
                NameDouble cellValu = data.value.get(j);
                XSSFCell cell = row.getCell(0);
                if (cell == null) {
                    cell = row.createCell(0);
                }
                cell.setCellValue(cellValu.name);

                cell = row.getCell(i + 1);
                if (cell == null) {
                    cell = row.createCell(i + 1);
                }
                cell.setCellValue(cellValu.value);
            }
            int lastRowNum = sheet.getLastRowNum();
            if (lastRowNum > size) {
                for (int idx = lastRowNum; idx > size; idx--) {
                    log.info("删除的行为:{}",idx);
                    sheet.removeRow(sheet.getRow(idx));
                }
            }
        }
    }

    /**
     * 替换 形如： Sheet1!$A$2:$A$4 的字符
     *
     * @param range
     * @return
     */
    public static String replaceRowEnd(String range, long oldSize, long newSize) {
        Pattern pattern = Pattern.compile("(:\\$[A-Z]+\\$)(\\d+)");
        Matcher matcher = pattern.matcher(range);
        if (matcher.find()) {
            long old = Long.parseLong(matcher.group(2));
            return range.replaceAll("(:\\$[A-Z]+\\$)(\\d+)", "$1" + Long.toString(old - oldSize + newSize));
        }
        return range;
    }
}
